- }.should_not change { @sent_posts.length }
+ }.should change { @sent_requests[Net::HTTP::Get].length }.by(1)
+ }.should_not change { @sent_requests[Net::HTTP::Post].length }
- @sent_gets[0].should == @checker.options['payload']
+ @sent_requests[Net::HTTP::Get][0].should == @checker.options['payload']
end
end
@@ -112,7 +135,7 @@ describe Agents::PostAgent do
@checker.should_not be_valid
end
- it "should validate method as post or get, defaulting to post" do
+ it "should validate method as post, get, put, patch, or delete, defaulting to post" do
@checker.options['method'] = ""
@checker.method.should == "post"
@checker.should be_valid
@@ -125,11 +148,35 @@ describe Agents::PostAgent do
@checker.method.should == "get"
@checker.should be_valid
+ @checker.options['method'] = "patch"
+ @checker.method.should == "patch"
+ @checker.should be_valid
+
@checker.options['method'] = "wut"
@checker.method.should == "wut"
@checker.should_not be_valid
end
+ it "should validate that no_merge is 'true' or 'false', if present" do
+ @checker.options['no_merge'] = ""
+ @checker.should be_valid
+
+ @checker.options['no_merge'] = "true"
+ @checker.should be_valid
+
+ @checker.options['no_merge'] = "false"
+ @checker.should be_valid
+
+ @checker.options['no_merge'] = false
+ @checker.should be_valid
+
+ @checker.options['no_merge'] = true
+ @checker.should be_valid
+
+ @checker.options['no_merge'] = 'blarg'
+ @checker.should_not be_valid
+ end
+
it "should validate payload as a hash, if present" do
@checker.options['payload'] = ""
@checker.should be_valid
@@ -178,7 +225,17 @@ describe Agents::PostAgent do
it "just returns the post_uri when no params are given" do
@checker.options['post_url'] = "http://example.com/a/path?existing_param=existing_value"
uri = @checker.generate_uri
+ uri.host.should == 'example.com'
+ uri.scheme.should == 'http'
uri.request_uri.should == "/a/path?existing_param=existing_value"
end
+
+ it "interpolates when receiving a payload" do
+ @checker.options['post_url'] = "https://{{ domain }}/{{ variable }}?existing_param=existing_value"
+ uri = @checker.generate_uri({ "some_param" => "some_value", "another_param" => "another_value" }, { 'domain' => 'google.com', 'variable' => 'a_variable' })
+ uri.request_uri.should == "/a_variable?existing_param=existing_value&some_param=some_value&another_param=another_value"
+ uri.host.should == 'google.com'
+ uri.scheme.should == 'https'
+ end
end
end
@@ -0,0 +1,81 @@ |
||
| 1 |
+require 'spec_helper' |
|
| 2 |
+ |
|
| 3 |
+describe Agents::RssAgent do |
|
| 4 |
+ before do |
|
| 5 |
+ @valid_options = {
|
|
| 6 |
+ 'expected_update_period_in_days' => "2", |
|
| 7 |
+ 'url' => "https://github.com/cantino/huginn/commits/master.atom", |
|
| 8 |
+ } |
|
| 9 |
+ |
|
| 10 |
+ stub_request(:any, /github.com/).to_return(:body => File.read(Rails.root.join("spec/data_fixtures/github_rss.atom")), :status => 200)
|
|
| 11 |
+ end |
|
| 12 |
+ |
|
| 13 |
+ let(:agent) do |
|
| 14 |
+ _agent = Agents::RssAgent.new(:name => "github rss feed", :options => @valid_options) |
|
| 15 |
+ _agent.user = users(:bob) |
|
| 16 |
+ _agent.save! |
|
| 17 |
+ _agent |
|
| 18 |
+ end |
|
| 19 |
+ |
|
| 20 |
+ it_behaves_like WebRequestConcern |
|
| 21 |
+ |
|
| 22 |
+ describe "validations" do |
|
| 23 |
+ it "should validate the presence of url" do |
|
| 24 |
+ agent.options['url'] = "http://google.com" |
|
| 25 |
+ agent.should be_valid |
|
| 26 |
+ |
|
| 27 |
+ agent.options['url'] = "" |
|
| 28 |
+ agent.should_not be_valid |
|
| 29 |
+ |
|
| 30 |
+ agent.options['url'] = nil |
|
| 31 |
+ agent.should_not be_valid |
|
| 32 |
+ end |
|
| 33 |
+ |
|
| 34 |
+ it "should validate the presence and numericality of expected_update_period_in_days" do |
|
| 35 |
+ agent.options['expected_update_period_in_days'] = "5" |
|
| 36 |
+ agent.should be_valid |
|
| 37 |
+ |
|
| 38 |
+ agent.options['expected_update_period_in_days'] = "wut?" |
|
| 39 |
+ agent.should_not be_valid |
|
| 40 |
+ |
|
| 41 |
+ agent.options['expected_update_period_in_days'] = 0 |
|
| 42 |
+ agent.should_not be_valid |
|
| 43 |
+ |
|
| 44 |
+ agent.options['expected_update_period_in_days'] = nil |
|
| 45 |
+ agent.should_not be_valid |
|
| 46 |
+ |
|
| 47 |
+ agent.options['expected_update_period_in_days'] = "" |
|
| 48 |
+ agent.should_not be_valid |
|
| 49 |
+ end |
|
| 50 |
+ end |
|
| 51 |
+ |
|
| 52 |
+ describe "emitting RSS events" do |
|
| 53 |
+ it "should emit items as events" do |
|
| 54 |
+ lambda {
|
|
| 55 |
+ agent.check |
|
| 56 |
+ }.should change { agent.events.count }.by(20)
|
|
| 57 |
+ end |
|
| 58 |
+ |
|
| 59 |
+ it "should track ids and not re-emit the same item when seen again" do |
|
| 60 |
+ agent.check |
|
| 61 |
+ agent.memory['seen_ids'].should == agent.events.map {|e| e.payload['id'] }
|
|
| 62 |
+ |
|
| 63 |
+ newest_id = agent.memory['seen_ids'][0] |
|
| 64 |
+ agent.events.first.payload['id'].should == newest_id |
|
| 65 |
+ agent.memory['seen_ids'] = agent.memory['seen_ids'][1..-1] # forget the newest id |
|
| 66 |
+ |
|
| 67 |
+ lambda {
|
|
| 68 |
+ agent.check |
|
| 69 |
+ }.should change { agent.events.count }.by(1)
|
|
| 70 |
+ |
|
| 71 |
+ agent.events.first.payload['id'].should == newest_id |
|
| 72 |
+ agent.memory['seen_ids'][0].should == newest_id |
|
| 73 |
+ end |
|
| 74 |
+ |
|
| 75 |
+ it "should truncate the seen_ids in memory at 500 items" do |
|
| 76 |
+ agent.memory['seen_ids'] = ['x'] * 490 |
|
| 77 |
+ agent.check |
|
| 78 |
+ agent.memory['seen_ids'].length.should == 500 |
|
| 79 |
+ end |
|
| 80 |
+ end |
|
| 81 |
+end |
@@ -4,23 +4,25 @@ describe Agents::WebsiteAgent do |
||
| 4 | 4 |
describe "checking without basic auth" do |
| 5 | 5 |
before do |
| 6 | 6 |
stub_request(:any, /xkcd/).to_return(:body => File.read(Rails.root.join("spec/data_fixtures/xkcd.html")), :status => 200)
|
| 7 |
- @site = {
|
|
| 7 |
+ @valid_options = {
|
|
| 8 | 8 |
'name' => "XKCD", |
| 9 |
- 'expected_update_period_in_days' => 2, |
|
| 9 |
+ 'expected_update_period_in_days' => "2", |
|
| 10 | 10 |
'type' => "html", |
| 11 | 11 |
'url' => "http://xkcd.com", |
| 12 | 12 |
'mode' => 'on_change', |
| 13 | 13 |
'extract' => {
|
| 14 |
- 'url' => { 'css' => "#comic img", 'attr' => "src" },
|
|
| 15 |
- 'title' => { 'css' => "#comic img", 'attr' => "alt" },
|
|
| 16 |
- 'hovertext' => { 'css' => "#comic img", 'attr' => "title" }
|
|
| 14 |
+ 'url' => { 'css' => "#comic img", 'value' => "@src" },
|
|
| 15 |
+ 'title' => { 'css' => "#comic img", 'value' => "@alt" },
|
|
| 16 |
+ 'hovertext' => { 'css' => "#comic img", 'value' => "@title" }
|
|
| 17 | 17 |
} |
| 18 | 18 |
} |
| 19 |
- @checker = Agents::WebsiteAgent.new(:name => "xkcd", :options => @site, :keep_events_for => 2) |
|
| 19 |
+ @checker = Agents::WebsiteAgent.new(:name => "xkcd", :options => @valid_options, :keep_events_for => 2) |
|
| 20 | 20 |
@checker.user = users(:bob) |
| 21 | 21 |
@checker.save! |
| 22 | 22 |
end |
| 23 | 23 |
|
| 24 |
+ it_behaves_like WebRequestConcern |
|
| 25 |
+ |
|
| 24 | 26 |
describe "validations" do |
| 25 | 27 |
before do |
| 26 | 28 |
@checker.should be_valid |
@@ -42,20 +44,6 @@ describe Agents::WebsiteAgent do |
||
| 42 | 44 |
@checker.should be_valid |
| 43 | 45 |
end |
| 44 | 46 |
|
| 45 |
- it "should validate headers" do |
|
| 46 |
- @checker.options['headers'] = "blah" |
|
| 47 |
- @checker.should_not be_valid |
|
| 48 |
- |
|
| 49 |
- @checker.options['headers'] = "" |
|
| 50 |
- @checker.should be_valid |
|
| 51 |
- |
|
| 52 |
- @checker.options['headers'] = {}
|
|
| 53 |
- @checker.should be_valid |
|
| 54 |
- |
|
| 55 |
- @checker.options['headers'] = { 'foo' => 'bar' }
|
|
| 56 |
- @checker.should be_valid |
|
| 57 |
- end |
|
| 58 |
- |
|
| 59 | 47 |
it "should validate mode" do |
| 60 | 48 |
@checker.options['mode'] = "nonsense" |
| 61 | 49 |
@checker.should_not be_valid |
@@ -97,16 +85,16 @@ describe Agents::WebsiteAgent do |
||
| 97 | 85 |
|
| 98 | 86 |
it "should always save events when in :all mode" do |
| 99 | 87 |
lambda {
|
| 100 |
- @site['mode'] = 'all' |
|
| 101 |
- @checker.options = @site |
|
| 88 |
+ @valid_options['mode'] = 'all' |
|
| 89 |
+ @checker.options = @valid_options |
|
| 102 | 90 |
@checker.check |
| 103 | 91 |
@checker.check |
| 104 | 92 |
}.should change { Event.count }.by(2)
|
| 105 | 93 |
end |
| 106 | 94 |
|
| 107 | 95 |
it "should take uniqueness_look_back into account during deduplication" do |
| 108 |
- @site['mode'] = 'all' |
|
| 109 |
- @checker.options = @site |
|
| 96 |
+ @valid_options['mode'] = 'all' |
|
| 97 |
+ @checker.options = @valid_options |
|
| 110 | 98 |
@checker.check |
| 111 | 99 |
@checker.check |
| 112 | 100 |
event = Event.last |
@@ -114,47 +102,47 @@ describe Agents::WebsiteAgent do |
||
| 114 | 102 |
event.save |
| 115 | 103 |
|
| 116 | 104 |
lambda {
|
| 117 |
- @site['mode'] = 'on_change' |
|
| 118 |
- @site['uniqueness_look_back'] = 2 |
|
| 119 |
- @checker.options = @site |
|
| 105 |
+ @valid_options['mode'] = 'on_change' |
|
| 106 |
+ @valid_options['uniqueness_look_back'] = 2 |
|
| 107 |
+ @checker.options = @valid_options |
|
| 120 | 108 |
@checker.check |
| 121 | 109 |
}.should_not change { Event.count }
|
| 122 | 110 |
|
| 123 | 111 |
lambda {
|
| 124 |
- @site['mode'] = 'on_change' |
|
| 125 |
- @site['uniqueness_look_back'] = 1 |
|
| 126 |
- @checker.options = @site |
|
| 112 |
+ @valid_options['mode'] = 'on_change' |
|
| 113 |
+ @valid_options['uniqueness_look_back'] = 1 |
|
| 114 |
+ @checker.options = @valid_options |
|
| 127 | 115 |
@checker.check |
| 128 | 116 |
}.should change { Event.count }.by(1)
|
| 129 | 117 |
end |
| 130 | 118 |
|
| 131 | 119 |
it "should log an error if the number of results for a set of extraction patterns differs" do |
| 132 |
- @site['extract']['url']['css'] = "div" |
|
| 133 |
- @checker.options = @site |
|
| 120 |
+ @valid_options['extract']['url']['css'] = "div" |
|
| 121 |
+ @checker.options = @valid_options |
|
| 134 | 122 |
@checker.check |
| 135 | 123 |
@checker.logs.first.message.should =~ /Got an uneven number of matches/ |
| 136 | 124 |
end |
| 137 | 125 |
|
| 138 | 126 |
it "should accept an array for url" do |
| 139 |
- @site['url'] = ["http://xkcd.com/1/", "http://xkcd.com/2/"] |
|
| 140 |
- @checker.options = @site |
|
| 127 |
+ @valid_options['url'] = ["http://xkcd.com/1/", "http://xkcd.com/2/"] |
|
| 128 |
+ @checker.options = @valid_options |
|
| 141 | 129 |
lambda { @checker.save! }.should_not raise_error;
|
| 142 | 130 |
lambda { @checker.check }.should_not raise_error;
|
| 143 | 131 |
end |
| 144 | 132 |
|
| 145 | 133 |
it "should parse events from all urls in array" do |
| 146 | 134 |
lambda {
|
| 147 |
- @site['url'] = ["http://xkcd.com/", "http://xkcd.com/"] |
|
| 148 |
- @site['mode'] = 'all' |
|
| 149 |
- @checker.options = @site |
|
| 135 |
+ @valid_options['url'] = ["http://xkcd.com/", "http://xkcd.com/"] |
|
| 136 |
+ @valid_options['mode'] = 'all' |
|
| 137 |
+ @checker.options = @valid_options |
|
| 150 | 138 |
@checker.check |
| 151 | 139 |
}.should change { Event.count }.by(2)
|
| 152 | 140 |
end |
| 153 | 141 |
|
| 154 | 142 |
it "should follow unique rules when parsing array of urls" do |
| 155 | 143 |
lambda {
|
| 156 |
- @site['url'] = ["http://xkcd.com/", "http://xkcd.com/"] |
|
| 157 |
- @checker.options = @site |
|
| 144 |
+ @valid_options['url'] = ["http://xkcd.com/", "http://xkcd.com/"] |
|
| 145 |
+ @checker.options = @valid_options |
|
| 158 | 146 |
@checker.check |
| 159 | 147 |
}.should change { Event.count }.by(1)
|
| 160 | 148 |
end |
@@ -170,7 +158,7 @@ describe Agents::WebsiteAgent do |
||
| 170 | 158 |
}, :status => 200) |
| 171 | 159 |
site = {
|
| 172 | 160 |
'name' => "Some JSON Response", |
| 173 |
- 'expected_update_period_in_days' => 2, |
|
| 161 |
+ 'expected_update_period_in_days' => "2", |
|
| 174 | 162 |
'type' => "json", |
| 175 | 163 |
'url' => "http://no-encoding.example.com", |
| 176 | 164 |
'mode' => 'on_change', |
@@ -197,7 +185,7 @@ describe Agents::WebsiteAgent do |
||
| 197 | 185 |
}, :status => 200) |
| 198 | 186 |
site = {
|
| 199 | 187 |
'name' => "Some JSON Response", |
| 200 |
- 'expected_update_period_in_days' => 2, |
|
| 188 |
+ 'expected_update_period_in_days' => "2", |
|
| 201 | 189 |
'type' => "json", |
| 202 | 190 |
'url' => "http://wrong-encoding.example.com", |
| 203 | 191 |
'mode' => 'on_change', |
@@ -248,11 +236,11 @@ describe Agents::WebsiteAgent do |
||
| 248 | 236 |
end |
| 249 | 237 |
|
| 250 | 238 |
it "parses XPath" do |
| 251 |
- @site['extract'].each { |key, value|
|
|
| 239 |
+ @valid_options['extract'].each { |key, value|
|
|
| 252 | 240 |
value.delete('css')
|
| 253 | 241 |
value['xpath'] = "//*[@id='comic']//img" |
| 254 | 242 |
} |
| 255 |
- @checker.options = @site |
|
| 243 |
+ @checker.options = @valid_options |
|
| 256 | 244 |
@checker.check |
| 257 | 245 |
event = Event.last |
| 258 | 246 |
event.payload['url'].should == "http://imgs.xkcd.com/comics/evolving.png" |
@@ -263,13 +251,12 @@ describe Agents::WebsiteAgent do |
||
| 263 | 251 |
it "should turn relative urls to absolute" do |
| 264 | 252 |
rel_site = {
|
| 265 | 253 |
'name' => "XKCD", |
| 266 |
- 'expected_update_period_in_days' => 2, |
|
| 254 |
+ 'expected_update_period_in_days' => "2", |
|
| 267 | 255 |
'type' => "html", |
| 268 | 256 |
'url' => "http://xkcd.com", |
| 269 | 257 |
'mode' => "on_change", |
| 270 | 258 |
'extract' => {
|
| 271 |
- 'url' => {'css' => "#topLeft a", 'attr' => "href"},
|
|
| 272 |
- 'title' => {'css' => "#topLeft a", 'text' => "true"}
|
|
| 259 |
+ 'url' => {'css' => "#topLeft a", 'value' => "@href"},
|
|
| 273 | 260 |
} |
| 274 | 261 |
} |
| 275 | 262 |
rel = Agents::WebsiteAgent.new(:name => "xkcd", :options => rel_site) |
@@ -280,6 +267,44 @@ describe Agents::WebsiteAgent do |
||
| 280 | 267 |
event.payload['url'].should == "http://xkcd.com/about" |
| 281 | 268 |
end |
| 282 | 269 |
|
| 270 |
+ it "should return an integer value if XPath evaluates to one" do |
|
| 271 |
+ rel_site = {
|
|
| 272 |
+ 'name' => "XKCD", |
|
| 273 |
+ 'expected_update_period_in_days' => 2, |
|
| 274 |
+ 'type' => "html", |
|
| 275 |
+ 'url' => "http://xkcd.com", |
|
| 276 |
+ 'mode' => "on_change", |
|
| 277 |
+ 'extract' => {
|
|
| 278 |
+ 'num_links' => {'css' => "#comicLinks", 'value' => "count(./a)"}
|
|
| 279 |
+ } |
|
| 280 |
+ } |
|
| 281 |
+ rel = Agents::WebsiteAgent.new(:name => "xkcd", :options => rel_site) |
|
| 282 |
+ rel.user = users(:bob) |
|
| 283 |
+ rel.save! |
|
| 284 |
+ rel.check |
|
| 285 |
+ event = Event.last |
|
| 286 |
+ event.payload['num_links'].should == "9" |
|
| 287 |
+ end |
|
| 288 |
+ |
|
| 289 |
+ it "should return all texts concatenated if XPath returns many text nodes" do |
|
| 290 |
+ rel_site = {
|
|
| 291 |
+ 'name' => "XKCD", |
|
| 292 |
+ 'expected_update_period_in_days' => 2, |
|
| 293 |
+ 'type' => "html", |
|
| 294 |
+ 'url' => "http://xkcd.com", |
|
| 295 |
+ 'mode' => "on_change", |
|
| 296 |
+ 'extract' => {
|
|
| 297 |
+ 'slogan' => {'css' => "#slogan", 'value' => ".//text()"}
|
|
| 298 |
+ } |
|
| 299 |
+ } |
|
| 300 |
+ rel = Agents::WebsiteAgent.new(:name => "xkcd", :options => rel_site) |
|
| 301 |
+ rel.user = users(:bob) |
|
| 302 |
+ rel.save! |
|
| 303 |
+ rel.check |
|
| 304 |
+ event = Event.last |
|
| 305 |
+ event.payload['slogan'].should == "A webcomic of romance, sarcasm, math, and language." |
|
| 306 |
+ end |
|
| 307 |
+ |
|
| 283 | 308 |
describe "JSON" do |
| 284 | 309 |
it "works with paths" do |
| 285 | 310 |
json = {
|
@@ -291,7 +316,7 @@ describe Agents::WebsiteAgent do |
||
| 291 | 316 |
stub_request(:any, /json-site/).to_return(:body => json.to_json, :status => 200) |
| 292 | 317 |
site = {
|
| 293 | 318 |
'name' => "Some JSON Response", |
| 294 |
- 'expected_update_period_in_days' => 2, |
|
| 319 |
+ 'expected_update_period_in_days' => "2", |
|
| 295 | 320 |
'type' => "json", |
| 296 | 321 |
'url' => "http://json-site.com", |
| 297 | 322 |
'mode' => 'on_change', |
@@ -322,7 +347,7 @@ describe Agents::WebsiteAgent do |
||
| 322 | 347 |
stub_request(:any, /json-site/).to_return(:body => json.to_json, :status => 200) |
| 323 | 348 |
site = {
|
| 324 | 349 |
'name' => "Some JSON Response", |
| 325 |
- 'expected_update_period_in_days' => 2, |
|
| 350 |
+ 'expected_update_period_in_days' => "2", |
|
| 326 | 351 |
'type' => "json", |
| 327 | 352 |
'url' => "http://json-site.com", |
| 328 | 353 |
'mode' => 'on_change', |
@@ -358,7 +383,7 @@ describe Agents::WebsiteAgent do |
||
| 358 | 383 |
stub_request(:any, /json-site/).to_return(:body => json.to_json, :status => 200) |
| 359 | 384 |
site = {
|
| 360 | 385 |
'name' => "Some JSON Response", |
| 361 |
- 'expected_update_period_in_days' => 2, |
|
| 386 |
+ 'expected_update_period_in_days' => "2", |
|
| 362 | 387 |
'type' => "json", |
| 363 | 388 |
'url' => "http://json-site.com", |
| 364 | 389 |
'mode' => 'on_change' |
@@ -382,7 +407,7 @@ describe Agents::WebsiteAgent do |
||
| 382 | 407 |
@event.payload = { 'url' => "http://xkcd.com" }
|
| 383 | 408 |
|
| 384 | 409 |
lambda {
|
| 385 |
- @checker.options = @site |
|
| 410 |
+ @checker.options = @valid_options |
|
| 386 | 411 |
@checker.receive([@event]) |
| 387 | 412 |
}.should change { Event.count }.by(1)
|
| 388 | 413 |
end |
@@ -394,20 +419,20 @@ describe Agents::WebsiteAgent do |
||
| 394 | 419 |
stub_request(:any, /example/). |
| 395 | 420 |
with(headers: { 'Authorization' => "Basic #{['user:pass'].pack('m').chomp}" }).
|
| 396 | 421 |
to_return(:body => File.read(Rails.root.join("spec/data_fixtures/xkcd.html")), :status => 200)
|
| 397 |
- @site = {
|
|
| 422 |
+ @valid_options = {
|
|
| 398 | 423 |
'name' => "XKCD", |
| 399 |
- 'expected_update_period_in_days' => 2, |
|
| 424 |
+ 'expected_update_period_in_days' => "2", |
|
| 400 | 425 |
'type' => "html", |
| 401 | 426 |
'url' => "http://www.example.com", |
| 402 | 427 |
'mode' => 'on_change', |
| 403 | 428 |
'extract' => {
|
| 404 |
- 'url' => { 'css' => "#comic img", 'attr' => "src" },
|
|
| 405 |
- 'title' => { 'css' => "#comic img", 'attr' => "alt" },
|
|
| 406 |
- 'hovertext' => { 'css' => "#comic img", 'attr' => "title" }
|
|
| 429 |
+ 'url' => { 'css' => "#comic img", 'value' => "@src" },
|
|
| 430 |
+ 'title' => { 'css' => "#comic img", 'value' => "@alt" },
|
|
| 431 |
+ 'hovertext' => { 'css' => "#comic img", 'value' => "@title" }
|
|
| 407 | 432 |
}, |
| 408 | 433 |
'basic_auth' => "user:pass" |
| 409 | 434 |
} |
| 410 |
- @checker = Agents::WebsiteAgent.new(:name => "auth", :options => @site) |
|
| 435 |
+ @checker = Agents::WebsiteAgent.new(:name => "auth", :options => @valid_options) |
|
| 411 | 436 |
@checker.user = users(:bob) |
| 412 | 437 |
@checker.save! |
| 413 | 438 |
end |
@@ -425,18 +450,18 @@ describe Agents::WebsiteAgent do |
||
| 425 | 450 |
stub_request(:any, /example/). |
| 426 | 451 |
with(headers: { 'foo' => 'bar', 'user_agent' => /Faraday/ }).
|
| 427 | 452 |
to_return(:body => File.read(Rails.root.join("spec/data_fixtures/xkcd.html")), :status => 200)
|
| 428 |
- @site = {
|
|
| 453 |
+ @valid_options = {
|
|
| 429 | 454 |
'name' => "XKCD", |
| 430 |
- 'expected_update_period_in_days' => 2, |
|
| 455 |
+ 'expected_update_period_in_days' => "2", |
|
| 431 | 456 |
'type' => "html", |
| 432 | 457 |
'url' => "http://www.example.com", |
| 433 | 458 |
'mode' => 'on_change', |
| 434 | 459 |
'headers' => { 'foo' => 'bar' },
|
| 435 | 460 |
'extract' => {
|
| 436 |
- 'url' => { 'css' => "#comic img", 'attr' => "src" },
|
|
| 461 |
+ 'url' => { 'css' => "#comic img", 'value' => "@src" },
|
|
| 437 | 462 |
} |
| 438 | 463 |
} |
| 439 |
- @checker = Agents::WebsiteAgent.new(:name => "ua", :options => @site) |
|
| 464 |
+ @checker = Agents::WebsiteAgent.new(:name => "ua", :options => @valid_options) |
|
| 440 | 465 |
@checker.user = users(:bob) |
| 441 | 466 |
@checker.save! |
| 442 | 467 |
end |
@@ -76,3 +76,39 @@ describe Event do |
||
| 76 | 76 |
end |
| 77 | 77 |
end |
| 78 | 78 |
end |
| 79 |
+ |
|
| 80 |
+describe EventDrop do |
|
| 81 |
+ def interpolate(string, event) |
|
| 82 |
+ event.agent.interpolate_string(string, event.to_liquid) |
|
| 83 |
+ end |
|
| 84 |
+ |
|
| 85 |
+ before do |
|
| 86 |
+ @event = Event.new |
|
| 87 |
+ @event.agent = agents(:jane_weather_agent) |
|
| 88 |
+ @event.payload = {
|
|
| 89 |
+ 'title' => 'some title', |
|
| 90 |
+ 'url' => 'http://some.site.example.org/', |
|
| 91 |
+ } |
|
| 92 |
+ @event.save! |
|
| 93 |
+ end |
|
| 94 |
+ |
|
| 95 |
+ it 'should be created via Agent#to_liquid' do |
|
| 96 |
+ @event.to_liquid.class.should be(EventDrop) |
|
| 97 |
+ end |
|
| 98 |
+ |
|
| 99 |
+ it 'should have attributes of its payload' do |
|
| 100 |
+ t = '{{title}}: {{url}}'
|
|
| 101 |
+ interpolate(t, @event).should eq('some title: http://some.site.example.org/')
|
|
| 102 |
+ end |
|
| 103 |
+ |
|
| 104 |
+ it 'should be iteratable' do |
|
| 105 |
+ # to_liquid returns self |
|
| 106 |
+ t = "{% for pair in to_liquid %}{{pair | join:':' }}\n{% endfor %}"
|
|
| 107 |
+ interpolate(t, @event).should eq("title:some title\nurl:http://some.site.example.org/\n")
|
|
| 108 |
+ end |
|
| 109 |
+ |
|
| 110 |
+ it 'should have agent' do |
|
| 111 |
+ t = '{{agent.name}}'
|
|
| 112 |
+ interpolate(t, @event).should eq('SF Weather')
|
|
| 113 |
+ end |
|
| 114 |
+end |
@@ -0,0 +1,88 @@ |
||
| 1 |
+require 'spec_helper' |
|
| 2 |
+ |
|
| 3 |
+shared_examples_for EmailConcern do |
|
| 4 |
+ let(:valid_options) {
|
|
| 5 |
+ {
|
|
| 6 |
+ :subject => "hello!", |
|
| 7 |
+ :expected_receive_period_in_days => "2" |
|
| 8 |
+ } |
|
| 9 |
+ } |
|
| 10 |
+ |
|
| 11 |
+ let(:agent) do |
|
| 12 |
+ _agent = described_class.new(:name => "some email agent", :options => valid_options) |
|
| 13 |
+ _agent.user = users(:jane) |
|
| 14 |
+ _agent |
|
| 15 |
+ end |
|
| 16 |
+ |
|
| 17 |
+ describe "validations" do |
|
| 18 |
+ it "should be valid" do |
|
| 19 |
+ agent.should be_valid |
|
| 20 |
+ end |
|
| 21 |
+ |
|
| 22 |
+ it "should validate the presence of 'subject'" do |
|
| 23 |
+ agent.options['subject'] = '' |
|
| 24 |
+ agent.should_not be_valid |
|
| 25 |
+ |
|
| 26 |
+ agent.options['subject'] = nil |
|
| 27 |
+ agent.should_not be_valid |
|
| 28 |
+ end |
|
| 29 |
+ |
|
| 30 |
+ it "should validate the presence of 'expected_receive_period_in_days'" do |
|
| 31 |
+ agent.options['expected_receive_period_in_days'] = '' |
|
| 32 |
+ agent.should_not be_valid |
|
| 33 |
+ |
|
| 34 |
+ agent.options['expected_receive_period_in_days'] = nil |
|
| 35 |
+ agent.should_not be_valid |
|
| 36 |
+ end |
|
| 37 |
+ |
|
| 38 |
+ it "should validate that recipients, when provided, is one or more valid email addresses" do |
|
| 39 |
+ agent.options['recipients'] = '' |
|
| 40 |
+ agent.should be_valid |
|
| 41 |
+ |
|
| 42 |
+ agent.options['recipients'] = nil |
|
| 43 |
+ agent.should be_valid |
|
| 44 |
+ |
|
| 45 |
+ agent.options['recipients'] = 'bob@example.com' |
|
| 46 |
+ agent.should be_valid |
|
| 47 |
+ |
|
| 48 |
+ agent.options['recipients'] = ['bob@example.com'] |
|
| 49 |
+ agent.should be_valid |
|
| 50 |
+ |
|
| 51 |
+ agent.options['recipients'] = ['bob@example.com', 'jane@example.com'] |
|
| 52 |
+ agent.should be_valid |
|
| 53 |
+ |
|
| 54 |
+ agent.options['recipients'] = ['bob@example.com', 'example.com'] |
|
| 55 |
+ agent.should_not be_valid |
|
| 56 |
+ |
|
| 57 |
+ agent.options['recipients'] = ['hi!'] |
|
| 58 |
+ agent.should_not be_valid |
|
| 59 |
+ |
|
| 60 |
+ agent.options['recipients'] = { :foo => "bar" }
|
|
| 61 |
+ agent.should_not be_valid |
|
| 62 |
+ |
|
| 63 |
+ agent.options['recipients'] = "wut" |
|
| 64 |
+ agent.should_not be_valid |
|
| 65 |
+ end |
|
| 66 |
+ end |
|
| 67 |
+ |
|
| 68 |
+ describe "#recipients" do |
|
| 69 |
+ it "defaults to the user's email address" do |
|
| 70 |
+ agent.recipients.should == [users(:jane).email] |
|
| 71 |
+ end |
|
| 72 |
+ |
|
| 73 |
+ it "wraps a string with an array" do |
|
| 74 |
+ agent.options['recipients'] = 'bob@bob.com' |
|
| 75 |
+ agent.recipients.should == ['bob@bob.com'] |
|
| 76 |
+ end |
|
| 77 |
+ |
|
| 78 |
+ it "handles an array" do |
|
| 79 |
+ agent.options['recipients'] = ['bob@bob.com', 'jane@jane.com'] |
|
| 80 |
+ agent.recipients.should == ['bob@bob.com', 'jane@jane.com'] |
|
| 81 |
+ end |
|
| 82 |
+ |
|
| 83 |
+ it "interpolates" do |
|
| 84 |
+ agent.options['recipients'] = "{{ username }}@{{ domain }}"
|
|
| 85 |
+ agent.recipients('username' => 'bob', 'domain' => 'example.com').should == ["bob@example.com"]
|
|
| 86 |
+ end |
|
| 87 |
+ end |
|
| 88 |
+end |
@@ -20,7 +20,7 @@ shared_examples_for LiquidInterpolatable do |
||
| 20 | 20 |
|
| 21 | 21 |
describe "interpolating liquid templates" do |
| 22 | 22 |
it "should work" do |
| 23 |
- @checker.interpolate_options(@checker.options, @event.payload).should == {
|
|
| 23 |
+ @checker.interpolate_options(@checker.options, @event).should == {
|
|
| 24 | 24 |
"normal" => "just some normal text", |
| 25 | 25 |
"variable" => "hello", |
| 26 | 26 |
"text" => "Some test with an embedded hello", |
@@ -30,7 +30,7 @@ shared_examples_for LiquidInterpolatable do |
||
| 30 | 30 |
|
| 31 | 31 |
it "should work with arrays", focus: true do |
| 32 | 32 |
@checker.options = {"value" => ["{{variable}}", "Much array", "Hey, {{hello_world}}"]}
|
| 33 |
- @checker.interpolate_options(@checker.options, @event.payload).should == {
|
|
| 33 |
+ @checker.interpolate_options(@checker.options, @event).should == {
|
|
| 34 | 34 |
"value" => ["hello", "Much array", "Hey, Hello world"] |
| 35 | 35 |
} |
| 36 | 36 |
end |
@@ -38,7 +38,7 @@ shared_examples_for LiquidInterpolatable do |
||
| 38 | 38 |
it "should work recursively" do |
| 39 | 39 |
@checker.options['hash'] = {'recursive' => "{{variable}}"}
|
| 40 | 40 |
@checker.options['indifferent_hash'] = ActiveSupport::HashWithIndifferentAccess.new({'recursive' => "{{variable}}"})
|
| 41 |
- @checker.interpolate_options(@checker.options, @event.payload).should == {
|
|
| 41 |
+ @checker.interpolate_options(@checker.options, @event).should == {
|
|
| 42 | 42 |
"normal" => "just some normal text", |
| 43 | 43 |
"variable" => "hello", |
| 44 | 44 |
"text" => "Some test with an embedded hello", |
@@ -49,8 +49,8 @@ shared_examples_for LiquidInterpolatable do |
||
| 49 | 49 |
end |
| 50 | 50 |
|
| 51 | 51 |
it "should work for strings" do |
| 52 |
- @checker.interpolate_string("{{variable}}", @event.payload).should == "hello"
|
|
| 53 |
- @checker.interpolate_string("{{variable}} you", @event.payload).should == "hello you"
|
|
| 52 |
+ @checker.interpolate_string("{{variable}}", @event).should == "hello"
|
|
| 53 |
+ @checker.interpolate_string("{{variable}} you", @event).should == "hello you"
|
|
| 54 | 54 |
end |
| 55 | 55 |
end |
| 56 | 56 |
|
@@ -0,0 +1,66 @@ |
||
| 1 |
+require 'spec_helper' |
|
| 2 |
+ |
|
| 3 |
+shared_examples_for WebRequestConcern do |
|
| 4 |
+ let(:agent) do |
|
| 5 |
+ _agent = described_class.new(:name => "some agent", :options => @valid_options || {})
|
|
| 6 |
+ _agent.user = users(:jane) |
|
| 7 |
+ _agent |
|
| 8 |
+ end |
|
| 9 |
+ |
|
| 10 |
+ describe "validations" do |
|
| 11 |
+ it "should be valid" do |
|
| 12 |
+ agent.should be_valid |
|
| 13 |
+ end |
|
| 14 |
+ |
|
| 15 |
+ it "should validate user_agent" do |
|
| 16 |
+ agent.options['user_agent'] = nil |
|
| 17 |
+ agent.should be_valid |
|
| 18 |
+ |
|
| 19 |
+ agent.options['user_agent'] = "" |
|
| 20 |
+ agent.should be_valid |
|
| 21 |
+ |
|
| 22 |
+ agent.options['user_agent'] = "foo" |
|
| 23 |
+ agent.should be_valid |
|
| 24 |
+ |
|
| 25 |
+ agent.options['user_agent'] = ["foo"] |
|
| 26 |
+ agent.should_not be_valid |
|
| 27 |
+ |
|
| 28 |
+ agent.options['user_agent'] = 1 |
|
| 29 |
+ agent.should_not be_valid |
|
| 30 |
+ end |
|
| 31 |
+ |
|
| 32 |
+ it "should validate headers" do |
|
| 33 |
+ agent.options['headers'] = "blah" |
|
| 34 |
+ agent.should_not be_valid |
|
| 35 |
+ |
|
| 36 |
+ agent.options['headers'] = "" |
|
| 37 |
+ agent.should be_valid |
|
| 38 |
+ |
|
| 39 |
+ agent.options['headers'] = {}
|
|
| 40 |
+ agent.should be_valid |
|
| 41 |
+ |
|
| 42 |
+ agent.options['headers'] = { 'foo' => 'bar' }
|
|
| 43 |
+ agent.should be_valid |
|
| 44 |
+ end |
|
| 45 |
+ |
|
| 46 |
+ it "should validate basic_auth" do |
|
| 47 |
+ agent.options['basic_auth'] = "foo:bar" |
|
| 48 |
+ agent.should be_valid |
|
| 49 |
+ |
|
| 50 |
+ agent.options['basic_auth'] = ["foo", "bar"] |
|
| 51 |
+ agent.should be_valid |
|
| 52 |
+ |
|
| 53 |
+ agent.options['basic_auth'] = "" |
|
| 54 |
+ agent.should be_valid |
|
| 55 |
+ |
|
| 56 |
+ agent.options['basic_auth'] = nil |
|
| 57 |
+ agent.should be_valid |
|
| 58 |
+ |
|
| 59 |
+ agent.options['basic_auth'] = "blah" |
|
| 60 |
+ agent.should_not be_valid |
|
| 61 |
+ |
|
| 62 |
+ agent.options['basic_auth'] = ["blah"] |
|
| 63 |
+ agent.should_not be_valid |
|
| 64 |
+ end |
|
| 65 |
+ end |
|
| 66 |
+end |
@@ -0,0 +1,9 @@ |
||
| 1 |
+require 'vcr' |
|
| 2 |
+ |
|
| 3 |
+VCR.configure do |c| |
|
| 4 |
+ c.cassette_library_dir = 'spec/cassettes' |
|
| 5 |
+ c.allow_http_connections_when_no_cassette = true |
|
| 6 |
+ c.hook_into :webmock |
|
| 7 |
+ c.default_cassette_options = { record: :new_episodes}
|
|
| 8 |
+ c.configure_rspec_metadata! |
|
| 9 |
+end |